package com.handinglian.ai.record.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.handinglian.ai.common.dto.CommonPage;
import com.handinglian.ai.common.util.FastJsonUtil;
import com.handinglian.ai.common.util.GeneralUtil;
import com.handinglian.ai.notice.param.DtmfCollectParam;
import com.handinglian.ai.record.dto.CallRecordDetailDto;
import com.handinglian.ai.record.dto.CallRecordDto;
import com.handinglian.ai.record.entity.CallDtmf;
import com.handinglian.ai.record.entity.CallRecord;
import com.handinglian.ai.record.entity.FileInfo;
import com.handinglian.ai.record.enums.CallTypeEnum;
import com.handinglian.ai.record.enums.RecordStateEnum;
import com.handinglian.ai.record.mapper.CallRecordMapper;
import com.handinglian.ai.record.param.CallRecordCreateParam;
import com.handinglian.ai.record.param.CallRecordPbxCreareParam;
import com.handinglian.ai.record.param.PushAiCallParam;
import com.handinglian.ai.record.service.CallDtmfService;
import com.handinglian.ai.record.service.CallRecordService;
import com.handinglian.ai.record.service.FileInfoService;
import com.handinglian.ai.system.dto.AnswerDto;
import com.handinglian.ai.thirdparty.dto.YyDtmfCollectDto;
import com.handinglian.ai.thirdparty.service.YunyiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CallRecordServiceImpl implements CallRecordService {
    @Autowired
    private CallRecordMapper callRecordMapper;
    @Autowired
    private FileInfoService fileInfoService;
    @Autowired
    private YunyiService yunyiService;
    @Autowired
    private CallDtmfService callDtmfService;

    @Override
    public int pushCdrInfo(List<CallRecordCreateParam> cdrBeans) {
        //筛选骚扰电话记录
        cdrBeans = cdrBeans.stream().filter(cdrBean -> StrUtil.isNotBlank(cdrBean.getStart_time())).collect(Collectors.toList());
        if (CollUtil.isEmpty(cdrBeans)){
            return 0;
        }

        List<CallRecord> callRecordList = new ArrayList<>();
        List<String> callidDbList = callRecordMapper.findCallid();
        List<String> callidParamList = new ArrayList<>();
        cdrBeans.forEach(cdrBean -> {
            callidParamList.add(cdrBean.getCall_uuid());
        });

        //筛选需要添加的通话记录
        List<String> addList = GeneralUtil.getAddList(callidParamList, callidDbList);
        cdrBeans = cdrBeans.stream().filter(cdrBean -> addList.contains(cdrBean.getCall_uuid())).collect(Collectors.toList());
        if (CollUtil.isEmpty(cdrBeans)){
            return -1;
        }

        cdrBeans.forEach(cdrBean -> {
            CallRecord callRecord = convertToCallRecord(cdrBean);
            callRecordList.add(callRecord);
        });

        int amount = callRecordMapper.batchInsert(callRecordList);

        return amount > 0?amount:-1;
    }

    @Override
    public int pushCdrPbx(List<CallRecordPbxCreareParam> creareParams) {
        //筛选骚扰电话记录
        creareParams = creareParams.stream().filter(cdrBean -> StrUtil.isNotBlank(cdrBean.getStarTime())).collect(Collectors.toList());
        if (CollUtil.isEmpty(creareParams)){
            return 0;
        }

        List<CallRecord> callRecordList = new ArrayList<>();
        List<String> callidDbList = callRecordMapper.findCallid();
        List<String> callidParamList = new ArrayList<>();
        creareParams.forEach(creareParam -> {
            callidParamList.add(creareParam.getCallid());
        });

        //筛选需要添加的通话记录
        List<String> addList = GeneralUtil.getAddList(callidParamList, callidDbList);
        creareParams = creareParams.stream().filter(cdrBean -> addList.contains(cdrBean.getCallid())).collect(Collectors.toList());
        if (CollUtil.isEmpty(creareParams)){
            return -1;
        }

        creareParams.forEach(creareParam -> {
            CallRecord callRecord = convertToCallRecord(creareParam);
            callRecordList.add(callRecord);
        });

        int amount = callRecordMapper.batchInsert(callRecordList);

        return amount > 0?amount:-1;
    }

    @Override
    public CommonPage<CallRecordDto> listPage(String startDate, String endDate, String callerNo, String calledNo, String recordStatus, String phoneStatus, String sortField, String sortOrder, Integer pageNum, Integer pageSize) {
        List<Integer> recordStatusList = GeneralUtil.stringToIntegerList(recordStatus);
        List<Integer> phoneStatusList = GeneralUtil.stringToIntegerList(phoneStatus);
        Date sDate = StrUtil.isBlank(startDate)?null:DateUtil.parseDateTime(startDate+" 00:00:00");
        Date eDate = StrUtil.isBlank(endDate)?null:DateUtil.parseDateTime(endDate+" 23:59:59");

        PageHelper.startPage(pageNum, pageSize);
        List<CallRecordDto> callRecordDtos = callRecordMapper.list(callerNo, calledNo, sDate, eDate, recordStatusList, phoneStatusList, sortField, sortOrder);
        return CommonPage.restPage(callRecordDtos);
    }

    @Override
    public CallRecordDetailDto getDetail(Integer id) {
        CallRecord callRecord = callRecordMapper.selectByPrimaryKey(id);
        CallRecordDetailDto callRecordDetailDto = FastJsonUtil.ObjToObjWithDateFormat(callRecord, CallRecordDetailDto.class);
        if (StrUtil.isBlank(callRecordDetailDto.getRecordFile())){
            callRecordDetailDto.setHasRecordFile(0);
        } else {
            callRecordDetailDto.setHasRecordFile(1);
        }
        return callRecordDetailDto;
    }

    @Override
    public CallRecordDetailDto getDetail(String callid) {
        CallRecord callRecord = callRecordMapper.findOneByCallid(callid);
        CallRecordDetailDto callRecordDetailDto = FastJsonUtil.ObjToObjWithDateFormat(callRecord, CallRecordDetailDto.class);
        if (StrUtil.isBlank(callRecordDetailDto.getRecordFile())){
            callRecordDetailDto.setHasRecordFile(0);
        } else {
            callRecordDetailDto.setHasRecordFile(1);
        }
        return callRecordDetailDto;
    }

    @Override
    public String download(String callid) throws IOException {
        FileInfo fileInfo = null;
        CallRecord callRecord = callRecordMapper.findOneByCallid(callid);
        if (StrUtil.isNotBlank(callRecord.getFileUuid())){
            fileInfo = fileInfoService.get(callRecord.getFileUuid());
            return fileInfo.getPath();
        }

        String recordFile = callRecord.getRecordFile();
        Integer index = recordFile.lastIndexOf("/");
        String recordName = recordFile.substring(index+1);
        yunyiService.downloadRecording(recordFile);

        fileInfo = newFileInfo(recordName);
        fileInfoService.create(fileInfo);

        callRecord.setFileUuid(fileInfo.getUuid());
        callRecordMapper.updateByPrimaryKeySelective(callRecord);
        return "/"+recordName;
    }

    @Override
    public int pushdtmf(String callee, String dtmf, String requestUUID) {
        CallDtmf callDtmf = new CallDtmf();
        callDtmf.setDtmf(dtmf);
        callDtmf.setCallee(callee);
        callDtmf.setRequestUuid(requestUUID);
        callDtmf.setCreateTime(new Date());
        return callDtmfService.updateByRequestUuid(callDtmf);
    }

    @Override
    public void dtmfCollect(DtmfCollectParam dtmfCollectParam) throws IOException {
        yunyiService.dtmfCollect(dtmfCollectParam);
    }

    private FileInfo newFileInfo(String fileName) {
        FileInfo fileInfo = new FileInfo();
        fileInfo.setUuid(GeneralUtil.randomUUID());
        fileInfo.setName(fileName);
        fileInfo.setPath("/"+fileName);
        fileInfo.setCreateTime(new Date());
        return fileInfo;
    }

    private CallRecord convertToCallRecord(CallRecordPbxCreareParam creareParam) {
        CallRecord callRecord = new CallRecord();
        callRecord.setStartTime(DateUtil.parseDateTime(creareParam.getStarTime()));

        Date endDate = DateUtil.offsetSecond(DateUtil.parseDateTime(creareParam.getStarTime()),Integer.valueOf(creareParam.getDurationTime()));
        callRecord.setEndTime(endDate);

        callRecord.setCallerNo(creareParam.getCallerNO());
        callRecord.setCalledNo(creareParam.getCalledNO());
        callRecord.setDurationTime(Integer.valueOf(creareParam.getDurationTime()));
        Integer phoneStatus = callRecord.getDurationTime() == 0?1:2;
        callRecord.setPhoneStatus(phoneStatus);
        callRecord.setRecordFile(creareParam.getRecordFile());
        callRecord.setCallid(creareParam.getCallid());
        callRecord.setCreateTime(new Date());
        callRecord.setRecordStatus(Integer.valueOf(creareParam.getRecordStatus()));
        callRecord.setRequestUuid(creareParam.getReqid());
        return callRecord;
    }

    private CallRecord convertToCallRecord(CallRecordCreateParam callRecordCreateParam) {
        CallRecord callRecord = new CallRecord();
        callRecord.setStartTime(DateUtil.parseDateTime(callRecordCreateParam.getStart_time()));

        Date endDate = DateUtil.offsetSecond(DateUtil.parseDateTime(callRecordCreateParam.getStart_time()),Integer.valueOf(callRecordCreateParam.getCall_lasts_time()));
        callRecord.setEndTime(endDate);

        callRecord.setCallerNo(callRecordCreateParam.getCaller_num());
        callRecord.setCalledNo(callRecordCreateParam.getCallee_num());
        if (callRecordCreateParam.getCall_type().equals(CallTypeEnum.CALL_IN.getKey())){
            callRecord.setCustomerNo(callRecordCreateParam.getCaller_num());
        } else if (callRecordCreateParam.getCall_type().equals(CallTypeEnum.AUTO_CALL_OUT.getKey())||callRecordCreateParam.getCall_type().equals(CallTypeEnum.MANUAL_CALL_OUT.getKey())){
            callRecord.setCustomerNo(callRecordCreateParam.getCallee_num());
        } else {
            callRecord.setCustomerNo(callRecord.getCalledNo());
        }
        callRecord.setDurationTime(Integer.valueOf(callRecordCreateParam.getCall_lasts_time()));
        Integer callType = Integer.valueOf(callRecordCreateParam.getCall_type());
        //pushCdrInfo接口呼叫标识为：1呼入2呼出4内线，改为：0呼入1呼出-1内线
        callType = callType.equals(1)?0:(callType.equals(2)?1:-1);
        callRecord.setRecordStatus(callType);
        Integer phoneStatus = Integer.valueOf(callRecordCreateParam.getCall_lasts_time()) == 0?1:2;
        callRecord.setPhoneStatus(phoneStatus);
        callRecord.setRecordFile(callRecordCreateParam.getRecordFile());
        callRecord.setCallid(callRecordCreateParam.getCall_uuid());
        callRecord.setCreateTime(new Date());
        return callRecord;
    }

    @Override
    public Integer countActualNum(Integer noticeId) {
        return callRecordMapper.countActualNum(noticeId);
    }

    @Override
    public Integer sumCallInDurationTime() {
        return callRecordMapper.sumCallInDurationTime();
    }

    @Override
    public Integer countCallIn() {
        return callRecordMapper.countCallIn();
    }

    @Override
    public Integer countCallInDaily() {
        Date now = new Date();
        String sDate = DateUtil.formatDate(now);
        sDate = sDate+" 00:00:00";
        Date startDate = DateUtil.parseDateTime(sDate);
        String eDate = DateUtil.formatDate(now);
        eDate = eDate+" 23:59:59";
        Date endDate = DateUtil.parseDateTime(eDate);
        return callRecordMapper.countCallInDaily(startDate, endDate);
    }

    @Override
    public Integer countCallOut() {
        return callRecordMapper.countCallOut();
    }

    @Override
    public Integer countCallOutAnswer() {
        return callRecordMapper.countCallOutAnswer();
    }

    @Override
    public List<AnswerDto> countAnswerYearly() {
        List<AnswerDto> answerDtos = new ArrayList<>();
        Date monthBegin = DateUtil.beginOfYear(new Date());
        Date monthEnd = DateUtil.endOfMonth(monthBegin);
        for (int i = 0;i < 12;i++){
            AnswerDto answerDto = new AnswerDto();
            int count = callRecordMapper.countCallInAnswerDateRange(monthBegin, monthEnd);
            answerDto.setAnswerNum(count);
            answerDto.setMonth(i+1);
            answerDtos.add(answerDto);

            monthBegin = DateUtil.offsetMonth(monthBegin, 1);
            monthEnd = DateUtil.offsetMonth(monthEnd,1);
        }
        return answerDtos;
    }
}
